package com.emperor.receipt.app;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;

import com.emperor.cashier.app.CashierAppCtrl;
import com.emperor.core.app.App;
import com.emperor.core.app.AppBase;
import com.emperor.core.app.AppConstant;
import com.emperor.core.logic.ReportDataSource;
import com.emperor.course.logic.Course;
import com.emperor.customer.logic.Customer;
import com.emperor.employee.logic.Employee;
import com.emperor.employee.logic.EmployeeModel;
import com.emperor.product.logic.Product;
import com.emperor.receipt.logic.Receipt;
import com.emperor.receipt.logic.ReceiptModel;
import com.emperor.transaction.logic.Transaction;
import com.emperor.transaction.logic.TransactionModel;
import com.emperor.treatment.logic.Treatment;
import com.emperor.util.DateFormatter;
import com.emperor.util.HibernateUtil;
import com.emperor.util.ReportUtil;
import com.swtdesigner.SWTResourceManager;

public class ReceiptAppEnq extends AppBase implements App {

	private Table table;
	private Text toText;
	private Text fromText;
	private Text text;
	protected Shell shell;

	public static Logger log = Logger.getLogger(ReceiptAppEnq.class);
	public SimpleDateFormat sdf = new SimpleDateFormat(DateFormatter.YYYYMMDD);

	private DecimalFormat df0;

	public ReceiptAppEnq() {
		super();
	}

	public ReceiptAppEnq(Map<String, Object> params) {
		super();
		this.params = params;
	}

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			ReceiptAppEnq window = new ReceiptAppEnq();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
		shell.setBackgroundImage(SWTResourceManager.getImage(
				ReceiptAppEnq.class, "/img/main.jpg"));
		shell.setImage(SWTResourceManager.getImage(ReceiptAppEnq.class,
				"/img/iMac OSX.png"));
		shell.setSize(1280, 800);
		shell.setText("Search Receipt");

		initScreen(shell, getParams());

		df0 = new DecimalFormat();
		df0.applyPattern("##########.##");
		df0.setMinimumFractionDigits(0);
		df0.setMaximumFractionDigits(0);

		final Composite composite = new Composite(shell, SWT.NONE);
		composite.setBounds(30, 50, 1197, 138);

		final Label customerNameLabel = new Label(composite, SWT.NONE);
		customerNameLabel.setBounds(10, 52, 115, 20);
		customerNameLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		customerNameLabel.setText("Receipt ID");

		text = new Text(composite, SWT.BORDER);
		text.setBounds(136, 49, 291, 30);
		text.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text.setToolTipText("receipt_id");

		final Label customerNameLabel_1 = new Label(composite, SWT.NONE);
		customerNameLabel_1.setBounds(10, 96, 115, 20);
		customerNameLabel_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		customerNameLabel_1.setText("From");

		final Label customerNameLabel_2 = new Label(composite, SWT.NONE);
		customerNameLabel_2.setBounds(441, 96, 20, 20);
		customerNameLabel_2.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		customerNameLabel_2.setText("To");

		fromText = new Text(composite, SWT.BORDER);
		fromText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		fromText.setToolTipText("fromText");
		fromText.setBounds(136, 98, 166, 25);

		toText = new Text(composite, SWT.BORDER);
		toText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		toText.setBounds(495, 98, 152, 25);
		toText.setToolTipText("fromText");

		final Button button = new Button(composite, SWT.NONE);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				pickDate(getShell(), fromText);
			}
		});
		button.setImage(SWTResourceManager.getImage(ReceiptAppEnq.class,
				"/img/Calendar.png"));
		button.setBounds(308, 96, 30, 30);
		button.setText("button");

		final Button button_1 = new Button(composite, SWT.NONE);
		button_1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				pickDate(getShell(), toText);
			}
		});
		button_1.setImage(SWTResourceManager.getImage(ReceiptAppEnq.class,
				"/img/Calendar.png"));
		button_1.setBounds(653, 92, 30, 30);
		button_1.setText("button");

		final Label messageLabel = new Label(composite, SWT.NONE);
		messageLabel.setBounds(10, 10, 1177, 25);
		messageLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));

		final Button searchButton = new Button(composite, SWT.NONE);
		searchButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				populateTable(table, text.getText(), fromText.getText(),
						toText.getText(), messageLabel);
			}
		});
		searchButton.setImage(SWTResourceManager.getImage(ReceiptAppEnq.class,
				"/img/Zoom-in.png"));
		searchButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		searchButton.setText("Search");
		searchButton.setBounds(709, 96, 90, 30);

		table = new Table(shell, SWT.FULL_SELECTION | SWT.BORDER);
		table.addMouseListener(new MouseAdapter() {
			public void mouseDoubleClick(final MouseEvent e) {
				viewReceipt(table);
			}
		});
		table.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		table.setLinesVisible(true);
		table.setHeaderVisible(true);
		table.setBounds(30, 194, 1083, 382);

		final TableColumn newColumnTableColumn = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn.setWidth(52);
		newColumnTableColumn.setText("No.");

		final TableColumn newColumnTableColumn_3 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_3.setWidth(117);
		newColumnTableColumn_3.setText("Date");

		final TableColumn newColumnTableColumn_1 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_1.setWidth(170);
		newColumnTableColumn_1.setText("Receipt Code");

		final TableColumn newColumnTableColumn_2 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_2.setWidth(100);
		newColumnTableColumn_2.setText("Payment");

		final TableColumn newColumnTableColumn_4 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_4.setWidth(227);
		newColumnTableColumn_4.setText("Customer");

		final TableColumn newColumnTableColumn_5 = new TableColumn(table,
				SWT.NONE);
		newColumnTableColumn_5.setWidth(100);
		newColumnTableColumn_5.setText("Total");

		final Button deleteButton = new Button(shell, SWT.NONE);
		deleteButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				int rowCount = doDeleteReceipt(table);
				if (rowCount == 1) {
					populateTable(table, text.getText(), fromText.getText(),
							toText.getText(), messageLabel);
				}
			}
		});
		deleteButton.setImage(SWTResourceManager.getImage(ReceiptAppEnq.class,
				"/img/Symbol-Delete.png"));
		deleteButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		deleteButton.setText("Delete");
		deleteButton.setBounds(30, 578, 85, 30);
		//
		buildStandardMenu(getShell(), getParams(), CashierAppCtrl.CASHIER_CTRL,
				CashierAppCtrl.CASHIER_FORM);
		populateTable(table, text.getText(), fromText.getText(),
				toText.getText(), messageLabel);
	}

	private void populateTable(Table table, String receiptId, String from,
			String to, Label label) {
		table.removeAll();
		table.clearAll();
		table.redraw();
		try {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();

			Criteria cris = session.createCriteria(ReceiptModel.class);

			if (!StringUtils.isEmpty(receiptId)) {
				cris.add(Expression.like(Receipt.FLD_CODE, "%" + receiptId
						+ "%"));
			}

			if (!StringUtils.isEmpty(from)) {
				cris.add(Expression.ge(Receipt.FLD_CRTDATE, sdf.parse(from)));
			}

			if (!StringUtils.isEmpty(to)) {
				cris.add(Expression.le(Receipt.FLD_CRTDATE, sdf.parse(to)));
			}

			cris.add(Expression.eq(Receipt.FLD_STATUS,
					AppConstant.STATUS_ACTIVE));

			List<Receipt> receipts = cris.list();
			if (receipts != null) {
				int count = 0;
				for (Iterator<Receipt> iter = receipts.iterator(); iter
						.hasNext();) {
					Receipt receipt = iter.next();
					count++;
					String custname = "";
					Customer customer = receipt.getCustomer();
					if (customer != null && customer.getId() != null) {
						custname = customer.getName();
					}

					TableItem item = new TableItem(table, SWT.BORDER);
					item.setText(new String[] { count + ".",
							sdf.format(receipt.getCrtdate()),
							receipt.getCode(), receipt.getPaymethod(),
							custname, df0.format(receipt.getTotal()) });
					item.setData(receipt);
				}

				if (count > 0) {
					label.setText(count + " receipt(s) found.");
				} else {
					label.setText("Please enter the receipt code, from, to and click search.");
				}
			}
		} catch (Exception e) {
			label.setText("No receipt found.");
			log.error(e.getMessage(), e);
		}
	}

	private int doDeleteReceipt(Table table) {
		int rowCount = 0;
		try {
			TableItem[] items = table.getSelection();
			if (items != null && items.length > 0) {
				for (int i = 0; i < items.length; i++) {
					TableItem item = items[i];
					if (item.getData() != null) {
						Receipt receipt = (Receipt) item.getData();

						MessageBox box = new MessageBox(getShell(),
								SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
						box.setText("Confirm Delete Receipt?");
						box.setMessage("Are you sure you want to delete this receipt?");

						int reply = box.open();
						if (reply == SWT.OK) {
							Session session = HibernateUtil.getSessionFactory()
									.getCurrentSession();

							try {
								session.beginTransaction();

								receipt.setStatus(AppConstant.STATUS_OBSOLETE);
								receipt = (Receipt) preUpdate(receipt,
										getParams());

								session.update(receipt);
								rowCount++;

								Criteria cris = session
										.createCriteria(TransactionModel.class);
								cris.add(Expression.eq(Transaction.FLD_RECEIPT,
										receipt));
								List<Transaction> transactions = cris.list();

								for (Iterator<Transaction> iter = transactions
										.iterator(); iter.hasNext();) {
									Transaction transaction = iter.next();
									transaction
											.setStatus(AppConstant.STATUS_OBSOLETE);
									transaction = (Transaction) preUpdate(
											transaction, getParams());

									session.update(transaction);
								}

								session.getTransaction().commit();
							} catch (Exception e) {
								session.getTransaction().rollback();
								throw e;
							}
						}
					}
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return rowCount;
	}

	public Shell getShell() {
		return shell;
	}

	public void setShell(Shell shell) {
		this.shell = shell;
	}

	private void printReceipt(Receipt receipt, List<Transaction> transactions,
			Employee employee) {
		Map params = new HashMap();
		try {
			if (receipt.getCustomer() != null
					&& receipt.getCustomer().getId() != null) {
				params.put(Customer.class.getSimpleName() + "."
						+ Customer.FLD_NAME, receipt.getCustomer().getName());
				params.put(Customer.class.getSimpleName() + "."
						+ Customer.FLD_CODE, receipt.getCustomer().getCode());
			}

			if (employee != null) {
				params.put(Employee.class.getSimpleName() + "."
						+ Employee.FLD_NAME, employee.getName());
			}

			params.put(Receipt.class.getSimpleName() + "." + Receipt.FLD_TOTAL,
					new Double(receipt.getTotal()));
			params.put(Receipt.class.getSimpleName() + "." + Receipt.FLD_PAID,
					new Double(receipt.getPaid()));
			params.put(
					Receipt.class.getSimpleName() + "." + Receipt.FLD_CHANGE,
					new Double(receipt.getChange()));
			params.put(Receipt.class.getSimpleName() + "."
					+ Receipt.FLD_CRTDATE, receipt.getCrtdate());
			params.put(Receipt.class.getSimpleName() + "." + Receipt.FLD_CODE,
					receipt.getCode());
			params.put(Receipt.class.getSimpleName() + "."
					+ Receipt.FLD_PAYMETHOD, receipt.getPaymethod());

			List list = new ArrayList();

			if (transactions != null && !transactions.isEmpty()) {
				Map record = new HashMap();
				for (Iterator<Transaction> iter = transactions.iterator(); iter
						.hasNext();) {
					Transaction transaction = iter.next();

					record = new HashMap();
					record.put("Quantity", transaction.getQuantity());
					record.put("Discount", transaction.getDiscount());
					record.put("Subtotal", transaction.getSubtotal());

					switch (transaction.getType()) {
					case Transaction.TYPE_COURSE:
						Course course = transaction.getCourse();
						if (course != null) {
							record.put("course_id", course.getId());
							record.put("Item", course.getName());
							record.put("Price", course.getPrice());
							record.put("SKU", course.getSku());
							record.put("Weight", 0);
							record.put("Weightuom", "");
						}
						break;
					case Transaction.TYPE_TREATMENT:
						Treatment treatment = transaction.getTreatment();
						if (treatment != null) {
							record.put("course_id", 0L);
							record.put("Item", treatment.getName());
							record.put("Price", treatment.getPrice());
							record.put("SKU", treatment.getSku());
							record.put("Weight", 0);
							record.put("Weightuom", "");
						}
						break;
					default:
						Product product = transaction.getProduct();
						if (product != null) {
							record.put("course_id", 0L);
							record.put("Item", product.getName());
							record.put("Price", product.getPrice());
							record.put("SKU", product.getSku());
							record.put("Weight", product.getWeight());
							record.put("Weightuom", product.getWeightuom());
						}
						break;
					}

					list.add(record);
				}
			} else {
				Map sample = new HashMap();

				sample.put("Quantity", new Double(0.0));
				sample.put("Item", "Not available");
				sample.put("Price", new Double(0.0));
				sample.put("Discount", new Double(0.0));
				sample.put("Subtotal", new Double(0.0));
				sample.put("SKU", "00000099");
				sample.put("Weight", new Double(0.0));
				sample.put("Weightuom", "ml");

				list.add(sample);
			}

			System.out.println("[" + params.toString() + "]");
			ReportDataSource dataSource = new ReportDataSource(list);
			ReportUtil.runReceiptPrint("./report/Receipt-Print.jrxml", params,
					dataSource, AppConstant.VIEW_REPORT);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("Unable to print receipt.", e);
		}
	}
	
	private void printReceipt(Long receiptId) {
		try {
			Map params = new HashMap();
			params.put("rcp_id", receiptId);
			ReportUtil.runReport("emperor", "root", "password", "./report/Receipt-DB-Print.jrxml", params);	
		} catch(Exception e) {
			log.error("Unable to print receipt.", e);
		}
	}

	private void viewReceipt(Table table) {
		try {
			System.out.println("in view receipt");
			TableItem[] items = table.getSelection();
			if (items != null && items.length > 0) {
				TableItem item = items[0];
				if (item.getData() != null) {
					Receipt receipt = (Receipt) item.getData();
					Session session = HibernateUtil.getSessionFactory()
							.getCurrentSession();
					List<Transaction> transactions = new ArrayList<Transaction>();
					Employee employee = null;
					try {
						session.beginTransaction();

						Criteria cris = session
								.createCriteria(TransactionModel.class);
						cris.add(Expression
								.eq(Transaction.FLD_RECEIPT, receipt));
						transactions = cris.list();

						cris = null;
						cris = session.createCriteria(EmployeeModel.class);
						cris.add(Expression.eq(Employee.FLD_ID,
								receipt.getCrtby()));
						List<Employee> employees = cris.list();
						if (employees != null && !employees.isEmpty()) {
							employee = employees.get(0);
						}
					} catch (Exception ex) {
						log.error(ex.getMessage(), ex);
						ex.printStackTrace();
					}
					System.out.println(receipt.getCode() + transactions.size()
							+ employee.getName());
					//printReceipt(receipt, transactions, employee);
					printReceipt(receipt.getId());
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			e.printStackTrace();
		}
	}
}
